#include "dbconnectionpool.h"

#include <QSqlError>

DBConnectionPool* DBConnectionPool::m_instance = nullptr;
QMutex DBConnectionPool::m_mutex;
QWaitCondition DBConnectionPool::m_condition;
int DBConnectionPool::m_name = 0;
DBConnectionPool* DBConnectionPool::GetInstance()
{

    if (m_instance == nullptr)
    {
        QMutexLocker locker(&m_mutex);
        if (m_instance == nullptr)
        {
            m_instance = new DBConnectionPool;
        }
    }
    return m_instance;
}

DBConnectionPool::DBConnectionPool()
{
    m_maxPoolSize = 10;
    for (m_name = 0; m_name < m_maxPoolSize; ++m_name)
    {
        CreateConnection(QString::number(m_name), "QODBC", "localhost", "XyChatData", "root", "1234");
    }
}

DBConnectionPool::~DBConnectionPool()
{
    // 主动断开和数据库的连接(别等自动断给操作系统找麻烦)
    while (!m_availableConnections.isEmpty()) {
        QSqlDatabase db = m_availableConnections.dequeue();
        db.close();
        QSqlDatabase::removeDatabase(db.connectionName());
    }
}

void DBConnectionPool::CreateConnection(const QString &dbName, const QString &dbType, const QString &host,
                                        const QString &dbname, const QString &user, const QString &password)
{
    // dbType是数据库驱动类型
    QSqlDatabase db = QSqlDatabase::addDatabase(dbType, dbName);
    db.setHostName(host);
    db.setDatabaseName(dbname); // 这里要使用odbc里配置的名字
    db.setUserName(user);
    db.setPassword(password);

    if (db.open()) {
        m_availableConnections.enqueue(db); // 将数据库连接加入连接池
    } else {
        // QSqlError error = db.lastError();
        qWarning() << "Error:" << db.lastError().text();
        qWarning() << "Failed to open database connection!";
    }
}

QSqlDatabase DBConnectionPool::AcquireConnection()
{
    QMutexLocker locker(&m_mutex);
    while (m_availableConnections.isEmpty())
    {
        // 如果无可用连接，当前线程释放锁进入阻塞，等其他线程归还连接后进入就绪状态
        m_condition.wait(&m_mutex);
    }
    return m_availableConnections.dequeue();
}

void DBConnectionPool::ReleaseConnection(QSqlDatabase db)
{
    QMutexLocker locker(&m_mutex);
    // 这里需要检查连接是否有效，数据库连接可能因为各种情况莫名断掉
    if (db.isOpen()) {
        m_availableConnections.enqueue(db);  // 将连接归还到池中
    }
    else {
        CreateConnection(QString::number(m_name), "QODBC", "localhost", "XyChatData", "root", "1234");
        ++m_name;
        qWarning() << "Released connection is invalid!";
    }
    m_condition.wakeOne();  // 唤醒因为队列空而进入阻塞的线程
}






